package Hxw3DEngine.core.display
{
	import flash.display3D.Context3D;
	import flash.display3D.IndexBuffer3D;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix3D;
	import Hxw3DEngine.core.component.renderer.Renderer3D;
	import Hxw3DEngine.core.component.Transform3D;
	import Hxw3DEngine.core.component.ComponentType;
	import flash.geom.Vector3D;
	import Hxw3DEngine.core.component.IComponent;
	import Hxw3DEngine.core.controller.RenderTree;
	import Hxw3DEngine.core.materials.Material3D;
	import Hxw3DEngine.core.controller.Camera3D;
	import Hxw3DEngine.proxy.Stage3DProxy;
	

	//基础3D对象
	public class GameObject extends EventDispatcher
	{
		private var _renderTree:RenderTree;
		
		public var depth:int;
		
		private var _transform:Transform3D;
		
		private var _parent:GameObject;
		
		//可渲染组件数量
		public var renderCount:uint;
		
		
		public function GameObject():void {
			_transform = new Transform3D;
			addComponent(_transform);
		}
		
		public function get transform():Transform3D {
			return _transform;
		}
		
		
		public function get renderTree():RenderTree {
			return _renderTree;
		}
		
		public function set renderTree(val:RenderTree):void {
			_renderTree = val;
		}
		
		
		//----------------------------------特殊属性----------------------------------------------
		
		
		private var _visible:Boolean = true;
		
		public function get visible():Boolean{
			return _visible;
		}
		
		public function set visible(value:Boolean):void{
			_visible = value;
		}
		
		public function get parent():GameObject {
			return _parent;
		}
		
		public function set parent(obj:GameObject):void {
			_parent = obj;
			transform.parent = obj.transform;
		}
		
		//---------------------------------可以作为容器------------------------------------------
		
		public function addChild(dis:GameObject,treeDepth:int = 0,depth:int = -1):void{
			dis.parent = this;
			renderTree.add(dis,-1);
		}
		
		public function removeChild(dis:GameObject):void{
			renderTree.remove(dis);
		}
		
		//-----------------------------------组件部分----------------------------------------------
		
		//组件库只读不写
		private var _components:Vector.<IComponent>;
		
		public function get components():Vector.<IComponent> {
			return _components ||= new Vector.<IComponent>;
		}
		
		/**
		 * 添加组件 
		 * @param com
		 */		
		public function addComponent(icom : IComponent) : void {
			if (components.indexOf(icom) != -1) {
				return;
			}
			if (icom is Renderer3D) renderCount ++;
			components.push(icom);
			icom.onAdd(this);
			for each (var c : IComponent in components) {
				c.onOtherComponentAdd(icom);
			}
		}
		
		/**
		 * 移除组件 
		 * @param com
		 */		
		public function removeComponent(icom : IComponent) : void {
			var idx : int = components.indexOf(icom);
			if (idx == -1) {
				return;
			}
			//静态组件不能移除
			if (icom.type == ComponentType.staticComponent) return ;
			
			if (icom is Renderer3D) renderCount --;
			
			components.splice(idx, 1);
			icom.onRemove(this);
			//通知所有组件有其它组件被移除
			for each (var c : IComponent in components) {
				c.onOtherComponentRemove(icom);
			}
		}
		
		/**
		 * 移除所有组件
		 */		
		public function removeAllComponents() : void {
			while (components.length) {
				this.removeComponent(components[0]);
			}
		}
		
		/**
		 * 根据类型获取component 
		 * @param clazz	类型
		 * @return 
		 */		
		public function getComponent(clazz : Class) : IComponent {
			for each (var icom : IComponent in components) {
				if (icom is clazz) {
					return icom;
				}
			}
			return null;
		}
		
		/**
		 * 根据类型获取components，低效率
		 * @param clazz		类型
		 * @param out		结果
		 * @return 			
		 */		
		public function getComponents(clazz : Class, out : Vector.<IComponent>) : Vector.<IComponent> {
			if (!out) {
				out = new Vector.<IComponent>();
			}
			for each (var icom : IComponent in components) {
				if (icom is clazz) {
					out.push(icom);
				}
			}
			return out;
		}	
		
		//----------------------------------渲染部分----------------------------------------
		//开始绘制
		public function draw():void {
			// mvp			
			Stage3DProxy.world.copyFrom(transform.world);
			Stage3DProxy.mvp.copyFrom(Stage3DProxy.world);
			Stage3DProxy.mvp.append(Stage3DProxy.viewProjection);
			
			Stage3DProxy.renderGameobjectCount ++;
			
			//绘制所有子节点
			for each(var comp:IComponent in components) {
				comp.onDraw();
			}
		}
		
	}
}